#include "tools/image_comparator.hpp"
#include "tools/image_viewer.hpp"
#include <iostream>
#include <algorithm>
#include <chrono>
#include <thread>

namespace toolsLib
{

// 构造函数：初始化默认参数
ImageComparator::ImageComparator()
    : mask_alpha_(0.5)  // 默认透明度为50%
    , tolerance_(0)     // 默认容差为0（完全匹配）
    , viewer_(std::make_unique<ImageViewer>())
{
}

// 析构函数：清理资源
ImageComparator::~ImageComparator()
{
    // 销毁所有显示窗口
    if (viewer_) {
        viewer_->destroyAllDisplay();
    }
}

// 比较两张图像，将不同的像素用红色透明蒙版遮盖
cv::Mat ImageComparator::compareImages(const cv::Mat& image1, const cv::Mat& image2)
{
    // ========== 步骤1：验证输入图像 ==========
    if (image1.empty() || image2.empty()) {
        std::cerr << "错误：输入图像为空" << std::endl;
        return cv::Mat();
    }

    // ========== 步骤2：复制图像以便修改 ==========
    cv::Mat img1 = image1.clone();
    cv::Mat img2 = image2.clone();

    // ========== 步骤3：转换为相同格式 ==========
    convertToSameFormat(img1, img2);

    // ========== 步骤4：调整到相同尺寸 ==========
    resizeToSameSize(img1, img2);

    // ========== 步骤5：创建差异掩码 ==========
    // 创建一个与图像相同尺寸的单通道掩码，标记不同的像素
    cv::Mat diff_mask = cv::Mat::zeros(img1.rows, img1.cols, CV_8UC1);

    int channels = img1.channels();
    
    // 逐个像素比较
    for (int y = 0; y < img1.rows; ++y) {
        for (int x = 0; x < img1.cols; ++x) {
            bool is_different = false;

            if (channels == 1) {
                // 灰度图像：直接比较像素值
                uint8_t val1 = img1.at<uint8_t>(y, x);
                uint8_t val2 = img2.at<uint8_t>(y, x);
                if (std::abs(static_cast<int>(val1) - static_cast<int>(val2)) > tolerance_) {
                    is_different = true;
                }
            } else if (channels == 3) {
                // BGR彩色图像：比较所有通道
                cv::Vec3b pixel1 = img1.at<cv::Vec3b>(y, x);
                cv::Vec3b pixel2 = img2.at<cv::Vec3b>(y, x);
                
                // 检查是否有任何通道的差值超过容差
                bool channel_diff = false;
                for (int c = 0; c < 3; ++c) {
                    if (std::abs(static_cast<int>(pixel1[c]) - static_cast<int>(pixel2[c])) > tolerance_) {
                        channel_diff = true;
                        break;
                    }
                }
                is_different = channel_diff;
            }

            // 如果像素不同，在掩码中标记
            if (is_different) {
                diff_mask.at<uint8_t>(y, x) = 255;
            }
        }
    }

    // ========== 步骤6：应用红色透明蒙版 ==========
    cv::Mat result = applyRedMask(img1, diff_mask);

    return result;
}

// 设置红色蒙版的透明度
void ImageComparator::setMaskAlpha(double alpha)
{
    // 限制透明度范围在 0.0 到 1.0 之间
    mask_alpha_ = std::max(0.0, std::min(1.0, alpha));
}

// 设置像素差异的容差值
void ImageComparator::setTolerance(int tolerance)
{
    // 容差值必须非负
    tolerance_ = std::max(0, tolerance);
}

// 调整图像尺寸使其相同
void ImageComparator::resizeToSameSize(cv::Mat& image1, cv::Mat& image2)
{
    // 如果尺寸相同，无需调整
    if (image1.rows == image2.rows && image1.cols == image2.cols) {
        return;
    }

    // 使用较大的尺寸作为目标尺寸
    int target_width = std::max(image1.cols, image2.cols);
    int target_height = std::max(image1.rows, image2.rows);

    // 调整图像尺寸
    if (image1.rows != target_height || image1.cols != target_width) {
        cv::resize(image1, image1, cv::Size(target_width, target_height), 0, 0, cv::INTER_LINEAR);
    }

    if (image2.rows != target_height || image2.cols != target_width) {
        cv::resize(image2, image2, cv::Size(target_width, target_height), 0, 0, cv::INTER_LINEAR);
    }
}

// 将图像转换为相同格式（统一为BGR格式）
void ImageComparator::convertToSameFormat(cv::Mat& image1, cv::Mat& image2)
{
    // 如果通道数相同，无需转换
    if (image1.channels() == image2.channels()) {
        // 如果都是单通道，保持灰度
        if (image1.channels() == 1) {
            return;
        }
        // 如果都是多通道，确保都是BGR格式
        if (image1.channels() == 3) {
            // 假设输入已经是BGR格式（OpenCV默认）
            return;
        }
    }

    // 统一转换为BGR格式（3通道）
    if (image1.channels() == 1) {
        cv::cvtColor(image1, image1, cv::COLOR_GRAY2BGR);
    }

    if (image2.channels() == 1) {
        cv::cvtColor(image2, image2, cv::COLOR_GRAY2BGR);
    }
}

// 比较两个像素值是否相同
bool ImageComparator::isPixelDifferent(const cv::Vec3b& pixel1, const cv::Vec3b& pixel2, int channels)
{
    for (int c = 0; c < channels; ++c) {
        if (std::abs(static_cast<int>(pixel1[c]) - static_cast<int>(pixel2[c])) > tolerance_) {
            return true;
        }
    }
    return false;
}

// 创建红色透明蒙版
cv::Mat ImageComparator::applyRedMask(const cv::Mat& image, const cv::Mat& diff_mask)
{
    // 创建结果图像（复制原图）
    cv::Mat result = image.clone();

    // 确保结果是BGR格式（3通道）
    if (result.channels() == 1) {
        cv::cvtColor(result, result, cv::COLOR_GRAY2BGR);
    }

    // 创建红色蒙版图像
    cv::Mat red_mask = cv::Mat::zeros(result.size(), CV_8UC3);
    red_mask.setTo(cv::Scalar(0, 0, 255));  // BGR格式的红色 (0, 0, 255)

    // 将红色蒙版应用到差异区域
    // 使用加权混合：result = (1 - alpha) * result + alpha * red_mask
    for (int y = 0; y < result.rows; ++y) {
        for (int x = 0; x < result.cols; ++x) {
            if (diff_mask.at<uint8_t>(y, x) > 0) {
                // 该像素有差异，应用红色蒙版
                cv::Vec3b& pixel = result.at<cv::Vec3b>(y, x);
                cv::Vec3b red = red_mask.at<cv::Vec3b>(y, x);

                // 混合原像素和红色蒙版
                for (int c = 0; c < 3; ++c) {
                    pixel[c] = static_cast<uint8_t>(
                        (1.0 - mask_alpha_) * pixel[c] + mask_alpha_ * red[c]
                    );
                }
            }
        }
    }

    return result;
}

// 重载：比较两张图像，返回不同像素的坐标和蒙版图像
void ImageComparator::compareImages(const cv::Mat& image1, const cv::Mat& image2, 
                                     std::vector<std::pair<int, int>>& diff_pixels, 
                                     cv::Mat& masked_image)
{
    // 清空输出参数
    diff_pixels.clear();
    masked_image = cv::Mat();

    // ========== 步骤1：验证输入图像 ==========
    if (image1.empty() || image2.empty()) {
        std::cerr << "错误：输入图像为空" << std::endl;
        return;
    }

    // ========== 步骤2：复制图像以便修改 ==========
    cv::Mat img1 = image1.clone();
    cv::Mat img2 = image2.clone();

    // ========== 步骤3：转换为相同格式 ==========
    convertToSameFormat(img1, img2);

    // ========== 步骤4：调整到相同尺寸 ==========
    resizeToSameSize(img1, img2);

    // ========== 步骤5：创建差异掩码并收集不同像素的坐标 ==========
    cv::Mat diff_mask = cv::Mat::zeros(img1.rows, img1.cols, CV_8UC1);

    int channels = img1.channels();
    
    // 逐个像素比较
    for (int y = 0; y < img1.rows; ++y) {
        for (int x = 0; x < img1.cols; ++x) {
            bool is_different = false;

            if (channels == 1) {
                // 灰度图像：直接比较像素值
                uint8_t val1 = img1.at<uint8_t>(y, x);
                uint8_t val2 = img2.at<uint8_t>(y, x);
                if (std::abs(static_cast<int>(val1) - static_cast<int>(val2)) > tolerance_) {
                    is_different = true;
                }
            } else if (channels == 3) {
                // BGR彩色图像：比较所有通道
                cv::Vec3b pixel1 = img1.at<cv::Vec3b>(y, x);
                cv::Vec3b pixel2 = img2.at<cv::Vec3b>(y, x);
                
                // 检查是否有任何通道的差值超过容差
                bool channel_diff = false;
                for (int c = 0; c < 3; ++c) {
                    if (std::abs(static_cast<int>(pixel1[c]) - static_cast<int>(pixel2[c])) > tolerance_) {
                        channel_diff = true;
                        break;
                    }
                }
                is_different = channel_diff;
            }

            // 如果像素不同，在掩码中标记并记录坐标
            if (is_different) {
                diff_mask.at<uint8_t>(y, x) = 255;
                diff_pixels.push_back(std::make_pair(x, y));  // 存储 (x, y) 坐标
            }
        }
    }

    // ========== 步骤6：应用红色透明蒙版 ==========
    masked_image = applyRedMask(img1, diff_mask);
}

// 比较并显示两张图像（在独立线程中执行，不阻塞调用线程）
void ImageComparator::compareImagesDisplay(const cv::Mat& image1, const cv::Mat& image2, const std::string& bind_name)
{
    if (image1.empty() || image2.empty()) {
        std::cerr << "错误：输入图像为空" << std::endl;
        return;
    }

    if (bind_name.empty()) {
        std::cerr << "错误：bind_name 不能为空" << std::endl;
        return;
    }

    // 复制图像数据（因为线程会异步使用）
    cv::Mat img1_copy = image1.clone();
    cv::Mat img2_copy = image2.clone();

    // 在独立线程中启动显示
    std::thread display_thread(displayThreadFunc, this, img1_copy, img2_copy, bind_name);
    display_thread.detach();  // 分离线程，不阻塞调用线程
}

// 销毁指定 bind_name 的绑定窗口
void ImageComparator::compareDisplayDestory(const std::string& bind_name)
{
    std::lock_guard<std::mutex> lock(viewer_mutex_);
    if (viewer_) {
        viewer_->destroyBindImage(bind_name);
    }
}

// 显示线程函数
void ImageComparator::displayThreadFunc(ImageComparator* comparator, 
                                         const cv::Mat& image1, 
                                         const cv::Mat& image2, 
                                         const std::string& bind_name)
{
    if (!comparator) {
        return;
    }

    // 获取 viewer 实例
    ImageViewer* viewer = nullptr;
    {
        std::lock_guard<std::mutex> lock(comparator->viewer_mutex_);
        if (!comparator->viewer_) {
            return;
        }
        viewer = comparator->viewer_.get();
    }

    // 调用重载的 compareImages 函数，获取不同像素坐标和蒙版图像
    std::vector<std::pair<int, int>> diff_pixels;
    cv::Mat masked_image;
    comparator->compareImages(image1, image2, diff_pixels, masked_image);

    if (masked_image.empty()) {
        std::cerr << "错误：比较失败" << std::endl;
        return;
    }

    // 使用 showBindImage 显示第一张图像
    viewer->showBindImage(image1, "image1", bind_name);

    // 使用 showBindImage 显示第二张图像
    viewer->showBindImage(image2, "image2", bind_name);

    // 使用 showBindImage 显示蒙版图像
    viewer->showBindImage(masked_image, "masked", bind_name);

    // 等待一小段时间，确保窗口已创建
    std::this_thread::sleep_for(std::chrono::milliseconds(100));

    // 设置窗口位置：
    // 窗口默认大小为 800x600
    // 上面的两个窗口紧挨着，居中在屏幕中间
    // 下面的窗口与上面的窗口有间距（避免边框重叠）
    const int window_width = 800;
    const int window_height = 600;
    const int start_y = 200;
    const int gap_horizontal = 0;  // 上面两个窗口之间的间距（紧挨着）
    const int gap_vertical = 40;   // 下面窗口与上面窗口的间距（避免边框重叠）
    
    // 假设屏幕宽度为 1920（可以根据实际情况调整）
    // 计算两个窗口的总宽度
    const int screen_width = 2560;
    const int two_windows_width = window_width * 2 + gap_horizontal;
    
    // 计算居中位置：让两个窗口在屏幕中间
    int start_x = (screen_width - two_windows_width) / 2;
    
    // image1 在左侧
    int image1_x = start_x;
    int image1_y = start_y;
    viewer->setWindowPosition("image1", image1_x, image1_y);
    
    // image2 在右侧，与 image1 紧挨着
    int image2_x = start_x + window_width + gap_horizontal;
    int image2_y = start_y;
    viewer->setWindowPosition("image2", image2_x, image2_y);
    
    // masked 在下方中间，与上面的窗口有间距
    // 计算两个窗口的中心点之间的中点
    int image1_center_x = image1_x + window_width / 2;
    int image2_center_x = image2_x + window_width / 2;
    int masked_center_x = (image1_center_x + image2_center_x) / 2;
    int masked_x = masked_center_x - window_width / 2;  // 窗口左上角位置
    int masked_y = start_y + window_height + gap_vertical;  // 在下方，有间距
    viewer->setWindowPosition("masked", masked_x, masked_y);

    // 将不同像素的边框修改为红色
    for (const auto& pixel : diff_pixels) {
        int x = pixel.first;
        int y = pixel.second;
        
        // 设置 image1 窗口的像素边框为红色
        viewer->setPixelBorderColor("image1", x, y, 0.0f, 1.0f, 0.0f);
        
        // 设置 image2 窗口的像素边框为红色
        viewer->setPixelBorderColor("image2", x, y, 0.0f, 0.0f, 1.0f);
    }
}

}  // namespace toolsLib

